2パス・アセンブラ&エディタ ――――――――――――――――――――――――――――――――――――――― I/O 1982年 9月号掲載 PC−8001 32K マシン語 08100H−096CFH S=08100H 起動方法 MON L G8100 ――――――――――――――――――――――――――――――――――――――― 2パス・アセンブラ&エディタ ザイログ形式のアセンブラ。 2パスでエディタ付! ………………………………………………… ザイログ型式のニモニックで Z80の全命令を網羅した 2パス・アセンブラを自作しました。 エディタ付きで かなり使いやすいものができたので 発表します。 ………………………………………………… ・―――――――――――――――――・ |■■■■■■用■■■語■■■■■■| ・―――――――――――――――――・ ここで使う言葉と記号の意味について 2、3説明しておきます。 テキス卜中の文字列で アセンブラが意味を解する最小単位のものを ここでは、ワードと呼ぶことにします。 たとえばテキスト例で、 『ORG』、『B004H』、『ASBL:』、『;』、『LD』、 などはそれぞれワードであり、 『DE,F754H』も1つのワードです。 また、1行とは画面上の実際の1行ではなく、 スクリーン・エディタにとっての1行という意味で 254文字までです。 ・―――――――――――――――――・ |■■■■■■使■用■法■■■■■■| ・―――――――――――――――――・ 始めに画面の横幅を80字または40字に設定してから、 モニタでアセンブラのテープをロードします。 終ったら、そのままモニタで8100へ飛んでください (*G8100[CR])。 タイトルが表示され、左端に“@”が出ます。 これはアセンブラのコマンド持ちであることを示します。 コマンドは小文字で入力できます。 コマンド・エラーはすべで“?”が出てやり直しとなります。 エラーメッセージは出ません。 アセンブラのコマンドを表1に示します。 表1 アセンブラ・コマンド ・―――――――――――――――――――――――――――――――――――――・ | ・――――――――――――――――――――――――――――――――・  | | |コマンド|  機  能   |リターンまたは中停止法      |  | | |――――+―――――――――+―――――――――――――――――|  | | | @A |アセンプル    |                 |  | | |――――+―――――――――+―――――――――――――――――|  | | | @AA|アセンブル&アセン|一時停止は [ESC]、続行は任意の  |  | | |    |ブル・リスト出力 |キー、中止は[STOP]        |  | | |――――+―――――――――+―――――――――――――――――|  | | | @M |モニタをコール  |[CTRL][b]でアセンブラへ     |  | | |    |         |リターン             |  | | |――――+―――――――――+―――――――――――――――――|  | | | @E |エディタをコール |#Rでアセンブラへリターン    |  | | |――――+―――――――――+―――――――――――――――――|  | | | @O |ラベル・テーブルを|一時停止、中止法は@AAの場合と |  | | |    |出力       |同じ。              |  | | ・――――――――――――――――――――――――――――――――・  | | 《注意》                                | |  (1)@Oを使う前には必ず@Aまたは@AAが              | |    実行されていなくてはなりません(暴走の恐れあり)。        | |                                     | |  (2)ラベル・テーブルの先頭アドレスはコールド・スタート時には     | |    E000にセットされています。                    | |                                     | |  (3)一時停止のとき [ESC]をゆっくり放すと               | |    1行、1行確実に送ることができます。               | |                                     | |  (4)@AA、@Oの場合、あらかじめ#&を使うか、           | |    またはテキスト中に随時“&”を(偶数個)入れることによって    | |    “プリンタ・セット”にすれば、リストをプリンタに出力できます。  | |    例参照。                             | ・―――――――――――――――――――――――――――――――――――――・ @E[CR] (先にも注意したように実際には@e[CR]と  小文字でよいのですが、以下大文字で記すことにします)とやれば エディタに移ります。 左端の“#”はエディタのコマンド入力持ちであることを意味します。 エディタのコマンドを表2に示します。 表2 エディタ・コマンド ・―――――――――――――――――――――――――――――――――――――・ |・―――――――――――――――――――――――――――――――――――・| || コマンド |         機        能         || ||――――――+――――――――――――――――――――――――――――|| ||#T    |LPから出力。            中停止法は@AAの|| ||#T.   |Pの1行を出力。              場合と同じ。|| ||#TA   |1行目から出力。                    || ||#Tn   |n行目から出力。                    || ||――――――+――――――――――――――――――――――――――――|| ||#P    |LPを最終行+1にセット。               || ||#Pn   |LPをnにセット。                   || ||#P+   |LPを1増加。                     || ||#P−   |LPを1減少。                     || ||――――――+――――――――――――――――――――――――――――|| ||#D    |LPの1行を消去。                   || ||#Dn   |n行目の1行を消去。                  || ||#DRn  |LPよりn行消去。                   || ||――――――+――――――――――――――――――――――――――――|| ||#I    |LPへ1行挿入。1行入力ごとにLPは1増加。      || ||      |コマンドの解消は単に[CR]。               || ||#C    |LPの1行を入れ替え。                 || ||――――――+――――――――――――――――――――――――――――|| ||#Wname  |CMTヘテキストをセーブ。nameは8字以内。       || ||#L    |CMTよりテキストをロード(’よりストア)。      || ||#LV   |ベリファイ。                      || ||――――――+――――――――――――――――――――――――――――|| ||#xnn  |テキスト先頭アドレスの変更。nは4桁16進数。      || ||      |コールド・スタート時には9700番地にセットされている。  || ||――――――+――――――――――――――――――――――――――――|| ||#,    |テキストの先頭アドレスの表示。             || ||#.    | 〃  のエンド・アドレスの表示。           || ||#/    |LPを表示。                      || ||――――――+――――――――――――――――――――――――――――|| ||#N    |new。テキスト消去(テキストの先頭に0を入れる)。  || ||――――――+――――――――――――――――――――――――――――|| ||#R    |アセンブラヘリターン。                 || ||――――――+――――――――――――――――――――――――――――|| ||#”……” |” ”内の文字列をLPよりサーチして表示。       || ||――――――+――――――――――――――――――――――――――――|| ||#&    |プリンタヘの出力スイッチ切替。             || ||      |プリンタ・セットでリストをプリンタヘ出力可。      || |・―――――――――――――――――――――――――――――――――――・| |*LPはライン・ポインタです。テキストの行を指します。          | |                                     | |《注意》                                 | |#”……”実行後表示されるメッセージの最初の数字は            | |何行目からサーチを始めたかを示します。                  | |つまり、LPの値です。                          | |これはミスを防ぐために付加しました。                   | ・―――――――――――――――――――――――――――――――――――――・ #Iコマンドでつぎつぎに入力してテキストを作成します。 #Iコマンド実行中は BASICのスクリーン・エディタとほとんど同じなので、 PCに慣れている人は気軽に使えると思います。 小文字で入力すれば自動的に大文字に変換されます。 ここでは後に掲げたテキスト例1を試しに入力してみてください。 終ったら#TAでリストをとって、 間違いのないことを確かめます。 念のため#Wでテープにセーブしておくとよいでしょう。 ネームは適肖に付けます。 #LVでセーブ・ミスのないことを確かめることもできます。 また、#&[CR]とやるとプリンタ・セットとなるので、 ここで#TAを使うとプリンタにテキストのリストが出力されます。 もう1度#&でプリンタ・リセットにすると プリンタには出力されなくなります。 テキスト例1 ・――――――――――――――――――――――――――――・ |0001 ORG B000H                     | |0002 ASBL: = 8104H                   | |0003 ; screen clear                   | |0004 LD A,0CH CALL 40A6H                | |0005 ;                         | |0006 LD DE,F754H LD HL,MSG               | |0007 LOOP: LD A,(HL) AND A JP Z,ASBL LD (DE),A     | |0008 INC DE INC HL LD A,(EA65H)             | |0009 CP 30H JR NC,LOOP INC DE JR LOOP          | |0010 MSG: "Good" !20476F64202100            | ・――――――――――――――――――――――――――――・ 次に、このテキストをアセンブルしてみましょう。 #Rでアセンブラに戻って@AA[CR] とやれば、 “LABEL TABLE FROM?” と表示されます。 これはラベル・テーブルをメモリ上のどこへ置くか、 その先頭アドレスの入力を要求しているのです。 16進数で番地を入力します(後にHをつける必要なし)。 また、何も入力せずに単に[CR]とするとE000番地より ラベル・テーブルを作成するようになっています。 テキストに誤りが無ければアセンブル・リストが画面に出ます (アセンブル・リスト1)。 アセンブル・リスト1 ・――――――――――――――――――――――――――――・ |B000 ORG B000H             | |B000 ASBL = 8104H             | | ;screen clear               | |B000 3E0C LD A,0CH             | |B002 CDA640 CALL 40A6H             | | ;                     | |B005 1154F7 LD DE,F754H           | |B008 211DB0 LD HL,MSG            | |B00B 7E LOOP LD A,(HL)            | |B00C A7 AND A               | |800D CA0401 JP Z,ASBL            | |B010 12 LD (DE),A            | |B011 13 INC DE              | |B012 23 INC HL              | |B013 3A65EA LD A,(EA65H)           | |B016 FE30 CP 30H              | |B018 30F1 JR NC,LOOP            | |B01A 13 INC DE              | |B01B 10EE JR LO0P             | |B01D 476F6F64 MSG "Good"            | |B021 20476F64 !20476F64           | |B025 202100 !202100            | ・――――――――――――――――――――――――――――・ アセンブル中にエラーが発見された場合には、 そのとき処埋中のワードが表示され、 さらにそれの存在する行が表示されて、エディタに制御が移ります。 エラーメッセージは出ません。 しかし、その問題のワードおよび その1つ前のワード(ニモニック)との関連などを考え合せると、 案外簡単にエラーの理由は判明するものです。 舌足らずのメッセージを出すよりも、 小システムではこうする方が有利だと考えました。 たとえば、ラベルでひっかかったとすると、 まずそのラベルは未定義であることが考えられます。 綴りの間違いなども吟昧しなくてはならないでしょう。 次に、ニモニックを見ます。 JRかDJNZの場合には相対ジャンプの許容範囲を 越えていることが考えられます(−126〜+129)。 その他、一般的にはニモニックと オペランドとのミスマッチも多いでしょうから、 Z80命令表を見て確かめます。 たとえばADDとSUBではオペランドの書式が異なります。 LDやIN、OUT命令 などでは( )の有無にも気をつけてください。 ここではこれ以上細かい例は挙げませんが、 やってみればすぐわかると思います。 エラーメッセージが出なくても心配無用、 ひっかかったワードが判明していれば、 意外と簡単にミスに気付くものです。 さて、アセンブルが終ったら@Oで ラベル・テーブルのリストを出してみます(ラベル・テーブル・リスト)。 ラベル・テーブル・リスト ・――――――――――――・ |  ASBL = 8104  | |  LOOP = B00B  | |  MSG = B01D  | ・――――――――――――・ 次にアセンブル・リストを部分的にプリンタに出してみましょう。 テキスト例1の6行目と7行目の間と9行目と10行目の間に それぞれ“&”を挿入します(テキスト例2)。 テキスト例2 ・――――――――――――――――――――――――――――・ |0001 ORG B000H                     | |0002 ASBL: = 8104H                   | |0003 ; screen clear                   | |0004 LD A,0CH CALL 40A6H                | |0005 ;                         | |0006 LD DE,F754H LD HL,MSG               | |0007 &                         | |0008 LOOP: LD A,(HL) AND A JP Z,ASBL LD (DE),A     | |0009 INC DE INC HL LD A,(EA65H)             | |0010 CP 30H JR NC,LOOP INC DE JR LOOP          | |0011 &                         | |0012 MSG: "Good" !20476F64202100            | ・――――――――――――――――――――――――――――・ ここでプリンタ・リセットの状態で@AAを実行すると、 “&”と“&”の間だけプリンタに出力されます(アセンブル・リスト2)。 また、プリンタ・セットにしておいて(#&で切り替え)、 @AA を実行すると、今度は逆に&と&の間だけ出力されません (アセンブル・リスト3)。 アセンブル・リスト2 ・――――――――――――――――――――――――――――・ |B00B 7E LOOP LD A,(HL)            | |B00C A7 AND A              | |B00D CA0481 JP Z,ASBL            | |B010 12 LD (DE),A            | |B011 13 INC DE              | |B012 23 INC HL              | |B013 3A65EA LD A,(EA65H)          | |B016 FE30 CP 30H             | |B010 30F1 JR NC,LOOP           | |B01A 13 INC DE              | |B018 18EE JR LOOP             | ・――――――――――――――――――――――――――――・ アセンブル・リスト3 ・――――――――――――――――――――――――――――・ |B000 ORG B000H             | |B000 ASBL = 8104H             | | ;screen clear               | |B000 3E0C LD A,0CH             | |B002 CDA640 CALL 40A6H             | | ;                     | |B005 1154F7 LD DE,F754H           | |B000 211DB0 LD HL,MSG            | |B01D 476F6F64 MSG "Good"            | |B021 20476F64 !20476F64           | |B025 202100 !202100            | ・――――――――――――――――――――――――――――・ このようにして、長いプログラムの場合、 そのアセンブル・リストを部分的にプリンタに出力することができるわけです。 テキスト中、“&”は何組でも、どこへでも入れることができます。 さて、この例ではアセンブルが完了すると、 オブジェクトはB000番地から 即実行できる形で格納されているはずです。 そこでこれを実行してみましょう。 @Mでモニタをコールして、 *GB000[CR]とやると画面中央にメッセージが出て アセンブラに戻るはずです。 これで、一応アセンブラとエディタの説明を終りますが、 その他、注意事項を箇条書きにしておきますからよく読んでください。 特に疑似・マクロ命令の ORGは 一般に使われているものと異なるので気を付けてください。 オフセット機能が第2オペランドとして付加されています。 最後に、“ドキュメント作成用エディタ・コマンド表”を見てください。 これは付録です。 エディタにほんの少し付け足すだけで、 ちょっとしたワード・プロセッサ的な機能が付け加えられるので 欲ばってみました。 案外役に立つと思います。 以上、説明不足の感じもしますが、 不明な点や疑問点があったらいろいろ試してみてください。 有益な情報が得られるでしょう。 この“やってみる”実験の精神が大切です。 表3 疑似・マクロ命令 ・―――――――――――――――――――――――――――――――――――――・ |・―――――――――――――――――――――――――――――――――――・| ||命 令|     機  能     | 例およびコメント       || ||―――+――――――――――――――+――――――――――――――――|| ||ORG|アセンブル開始番地の指定  |(1)ORG C000H         || ||   |オフセット番地の指定    |(2)ORG A000H,B000H      || ||   |              | 下の注意(1)を参照      || ||―――+――――――――――――――+――――――――――――――――|| || = |ラベルの定義        |Loop: = C000H          || ||   |(左辺には必ず:を付すこと)|END: = Loop+23         || ||―――+――――――――――――――+――――――――――――――――|| || ; |コメント          |; コレハCommentデアル        || ||   |(行の終りに書くこと)   | (31字まで有効)       || ||―――+――――――――――――――+――――――――――――――――|| || ! |16進nバイトをストア    |!C035ADB0            || ||―――+――――――――――――――+――――――――――――――――|| ||”…”|ASCIIコードをストア  |"ABC"(=!414243)         || ||―――+――――――――――――――+――――――――――――――――|| || # |10進数を1バイトまたは   |#12 (=!0C)           || ||   |2バイトをストア      |#267(=!0B01)          || ||―――+――――――――――――――+――――――――――――――――|| ||DW |下位、上位の順で2バイトを |DW 1234H(=!3412)        || ||   |ストア           |DW 276(=!0B01)         || ||   |              |DW LABEL            || ||―――+――――――――――――――+――――――――――――――――|| ||*BC|BCレジスタ・ペアの内容表示|アセンブラかメモリ内に存在しない|| ||*DE|DE     〃      |ときには使えない。       || ||*HL|HL     〃      |                || ||*AF|Acc、FLAG 〃    |                || ||―――+――――――――――――――+――――――――――――――――|| || & |プリンタ出力スイッチ切替。 |アセンブル・リストを部分的に  || ||   |機能はエディタ・コマンドの |プリンタに出力するときに使う。 || ||   |#&と同じ。        |                || |・―――――――――――――――――――――――――――――――――――・| |《注意》                                 | |(1)ORGにはオフセット機能が付加されているので注意してください。    | |  例(1)の場合、C000番地からアセンブルを開始し、           | |  生成されたオブジェクトもC000番地から格納していきます。        | |  例(2)の場合、A000番地からアセンブルを開始し、           | |  B000番地よりオブジェクトを格納してゆきます。             | |  従ってB000番地からの内容をA000番地からに転送しないと         | |  一般には実行できません。                       | |  この機能はROMの開発などに利用できます。              | |                                     | |(2)“&”は偶数個なら何個使ってもかまいません。             | |  奇数個の場合でもそれなりに動作しますが、               | |  コントロールは難かしくなります。                   | ・―――――――――――――――――――――――――――――――――――――・ 表4 ドキュメント作成用エディタ・コマンド ・―――――――――――――――――――――――――――――――――――――・ |・―――――――――――――――――――――――――――――――――――・| ||コマンド|      機 能 お よ び コ メ ン ト       || ||――――+――――――――――――――――――――――――――――――|| ||#IY |小文字は小文字のまま入力。                 || ||#CY |他はそれぞれ#I、#Cと同じ。               || ||――――+――――――――――――――――――――――――――――――|| ||#Y  |                              || ||#Y. |行番号を表示しない。                    || ||#Y. |他は#T群と同じ。                     || ||#YA |                              || ||――――+――――――――――――――――――――――――――――――|| ||#Un |                              || ||#U. |行番号を1行上に表示し、文は左端より表示。         || ||#U. |他は#T群と同じ。                     || ||#UA |                              || ||――――+――――――――――――――――――――――――――――――|| ||#Sn |プリンタヘ1行ずつリアル・タイム出力。           || ||    |このコマンドを中止したいときは何も入力せず単に[CR]。    || ||#%  |画面コピー。                        || |・―――――――――――――――――――――――――――――――――――・| |                                     | ・―――――――――――――――――――――――――――――――――――――・ ・―――――――――――――――――・ |■■■テキスト作成上の注意■■■■| ・―――――――――――――――――・ ■ニモニックやオペランドの書式は文献1に従いました。 ■マルチステートメントが可能です(テキスト例参照)。  スペースは1個以上何個でもよい。 ■16進数は2桁または4桁にすること。      AHとか123Hは不可。      それぞれ、0AH、0123Hとする。 ■ラベルの定義には必ずコロン:を付すこと。      LABEL:LD A,B      Loop: = LABEL+12 ■16進数で直接定義するときには適宜、前に0を付して4桁にすること。      LABEL: = 00BCH ■LD命令、論理演算命令などでは1バイト数のかわりに、  ASCIIコードが使えます。      LD A,"M" (=LD A,4DH)      CP "e"  (=CP 65H) ■オペランドに符号付き16進または10進数を書けば、  現在の番地に対する相対番地が指定できます。      JR NZ,+8 JP +1234H      CALL -0AH DJNZ -16 ■ラベルの後に符号付き16進または10進数を書いて加減算ができます。      JP LABEL+0123H      LD HL,loop-12 ■IN、OUT命令においてポート番号にラベルが使えます。  この場合、上位1バイトは無視され下位1バイトがポート番号を意味します。  したがって、ラベルを定義するときには先頭に00を付します。      PORT: =0030H (ポート 30H)      OUT (PORT),A ■16進数には必ずHを付けます。  Hを落とすと10進数とみなされます。 ・―――――――――――――――――・ |■■■■その他一般的な注意■■■■| ・―――――――――――――――――・ ■CMT関係のエラーやその他のトラブルで[CTRL][b]で  アセンブラに戻れなくなったときには、  8104番地(ホット・スタート)に飛ぶと  テキストはそのまま保存されます  (アセンブラが壊れていない限り)。  8100番地(コールド・スタート)から入ると  テキストの先頭に0が入ってしまい、修復が必要になります。 ■アセンブラ、テキスト、ラベル・テーブル、オブジェクトの4つが  メモリ内に同居するので、  お互いの領域か重ならないように充分注意してください。  このようなトラブルに関するメッセージは一切出ません。  ときどきモニタの*Dコマンドでメモリ内を覗いてください。  暴走したり、アセンブラの動作が変になったらまず、  この領域の重複がないかを確かめる必要があります。 ■アセンブラの制作に当っては文献1の巻末のZ80命令表を使いました  (ただし、“SBC s” は“SBC A,s” のミス・プリントと   判断して筆者が勝手に改めました)。 ・―――――――――――――――――・ |■■■■■あ■と■が■き■■■■■| ・―――――――――――――――――・ このアセンブラは佐々木氏の2パス・アセンブラ(文献2)を使って 作成したものです。 筆者は氏のアセンブラしか知らないので、 視野の狭さからくる誤解や、偏見のあることを恐れます。 小さなマイコンの持つ能力をフルに引き出すためには、 どうしても機械語が必要になることでしょう。 そんなとき、このアセンブラが少しでも皆さんの役に立てば幸いです。 最後にこのアセンブラの制作中、 いろいろ有益なご意見を寄せられ、 この発表を勧めてくださった田端氏にこの誌面を借りて感謝の意を表します。 【】参考文献 1)Z-80マイクロコンピューター(マイクロコンピュータシリーズII)、丸善。 2)I/O、’80年12月号、工学社。 3)その他不特定多数の雑誌のPCのROMに関する記事。